<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>文件切片上传</title>
</head>

<body>
    <input type="file" id="file">
    <script>
        // 请求封装
        // 1. http 并发 blob上传 chunk  / POST
        // 2. 当blob Promise.all 上传成功之后 再发送一个merge的请求 /merge
        function request({
            url,
            method = 'POST',
            data,
            headers = {},
            requestList // 上传的文件列表
        }) {
            return new Promise(resolve => {
                const xhr = new XMLHttpRequest(); // js ajax 对象
                xhr.open(method, url); // 打开某个url的请求
                Object.keys(headers).forEach(key => {
                    xhr.setRequestHeader(key, headers[key]) // 如果传了请求头进来 给请求加头信息
                })
                xhr.send(data); // 发送数据
                xhr.onload = e => { 
                    resolve({
                        data: e.target.response // 服务器端返回的数据
                    });
                }
            })
        }

        const mergeRequest = async () => {
            await request({
                url: 'http://localhost:3001/merge',
                headers: {
                    "content-type": "application/json"
                }
            });
            alert('上传成功')
        }
        
        document
            .getElementById('file')
            .addEventListener('change', async (event) => {
                const file = event.target.files[0]; // ES6 文件对象 拿到上传到的文件对象
                // console.log(file)
                const file_name = file.name.split('.')[0]; // 上传的文件的名字
                // console.log(Object.prototype.toString.call(file));  // [object File]
                // console.log(Object.prototype.toString.call(file.slice(0, 102400))); // array slice [object Blob]
                let cur = 0, size = 0.5 * 1024 * 1024; // 1M
                const fileChunkList = []; // 分割出来的 blob 数组
                while (cur < file.size) {
                    fileChunkList.push({
                        // cur offset, end 
                        file: file.slice(cur, cur + size) // 文件分片
                    });
                    cur += size;
                }
                // console.log(fileChunkList);
                const requestList = fileChunkList // 将每个切片发送一个请求发送给后端
                    .map(({ file }, index) => {
                        const formData = new FormData(); // js post form 
                        formData.append("chunk", file); // 添加传输表单数据 二进制文件 切片文件
                        formData.append("filename", `${file_name}-${index}`); // 切片文件的名字
                        return {
                            formData
                        }
                    })
                    .map(async ({ formData }) => request({
                        url: 'http://localhost:3000', // 前后端的连接点
                        data: formData
                    }))
                console.log(requestList);
                await Promise.all(requestList); // 并发
                await mergeRequest();
            })
    </script>
</body>

</html>